package com.qqs.stock.handler;

import com.qqs.stock.constant.DeductStockConstant;
import com.qqs.stock.dao.DeductStockDao;
import com.qqs.stock.dao.LocalDeductStockDao;
import com.qqs.stock.dto.DeductStockOrderDto;
import com.qqs.stock.dto.DeductStockOrderPromise;
import com.qqs.stock.exception.DeductStockException;
import com.qqs.stock.utils.DeductStockConvert;
import com.qqs.stock.vo.DeductStockOrderVo;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;


@Slf4j
public class DefaultDeductStockHandler implements DeductStockHandler {

    private final DefaultDeductStockMerge merge;
    private final DeductStockDao deductStockDao = new LocalDeductStockDao();

    public DefaultDeductStockHandler() {
        merge = new DefaultDeductStockMerge();
    }

    public DefaultDeductStockHandler(DefaultDeductStockMerge merge) {
        this.merge = merge;
    }

    @Override
    public DeductStockOrderVo handler(DeductStockOrderDto deductStockOrder) {
        // 幂等性处理
        if (idempotency(deductStockOrder)) {
            DeductStockOrderVo response = DeductStockConvert.responseConvert(deductStockOrder);
            response.setStatus(DeductStockConstant.Status.PROCESSED_SUCCESSFUL.getCode());
            response.setMessage(DeductStockConstant.Status.PROCESSED_SUCCESSFUL.getMessage());
            return response;
        }

        final DeductStockOrderPromise promise = DeductStockConvert.convert(deductStockOrder);
        promise.lock();
        try {
            // 入队列
            try {
                boolean merge = this.merge.merge(promise);
                if (!merge) {
                    promise.setStatus(DeductStockConstant.Status.UNKNOWN_ERROR.getCode());
                    promise.setMessage(DeductStockConstant.Status.UNKNOWN_ERROR.getMessage());
                    DeductStockException.newThrow(promise);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                promise.setStatus(DeductStockConstant.Status.UNKNOWN_ERROR.getCode());
                promise.setMessage(DeductStockConstant.Status.UNKNOWN_ERROR.getMessage());
                DeductStockException.newThrow(e.getMessage(), e, promise);
            }
            // 等待
            try {
                boolean await = promise.await(200, TimeUnit.SECONDS);
                if (!await) {
                    promise.setStatus(DeductStockConstant.Status.OVERTIME.getCode());
                    promise.setMessage(DeductStockConstant.Status.OVERTIME.getMessage());
                    DeductStockException.newThrow(DeductStockConstant.Status.OVERTIME.getMessage(), promise);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                promise.setStatus(DeductStockConstant.Status.UNKNOWN_ERROR.getCode());
                promise.setMessage(DeductStockConstant.Status.UNKNOWN_ERROR.getMessage());
                DeductStockException.newThrow(e.getMessage(), e, promise);
            }
            // 处理完成
            DeductStockOrderVo response = DeductStockConvert.convert(promise);
            System.out.println(response);
            // 返回
            return response;
        } finally {
            promise.unlock();
        }

    }

    private boolean idempotency(DeductStockOrderDto deductStockOrder) {
        int count = deductStockDao.selectBillCount(deductStockOrder.getOrderId(), deductStockOrder.getWarId());
        return count > 0;
    }
}
